package com.zhl.study.service.chainResponsibility;

import com.zhl.study.anno.Duty;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
 * @description TODO
 * @Author: z156940l@outlook.com
 * @className ProductChainFactory
 * @Date: 2024/12/26 22:48
 */
public class ProductChainFactory {
    /**
     * 存放责任链路上的具体处理类
     * k-具体业务场景枚举
     * v-具体业务场景下的责任链路集合
     */
    private Map<String, List<IHandler>> handleMap;

    /**
     * 存放系统中责任链具体处理类
     * @param handlerList
     */
    public  ProductChainFactory(List<IHandler> handlerList) {
        Map<String, List<IHandler>> collect = handlerList.stream()
                .sorted(Comparator.comparingInt(h -> AnnotationUtils.findAnnotation(h.getClass(), Duty.class).order()))
                // 将duty.type[]  形成  map<type, handler>
                .flatMap(handler -> {
                    Duty duty = AnnotationUtils.findAnnotation(handler.getClass(), Duty.class);
                    if (duty != null && duty.type() != null) {
                        return Arrays.stream(duty.type())
                                .map(type -> new AbstractMap.SimpleEntry<>(type, handler));
                    } else {
                        return Stream.empty();
                    }
                })
                // 分组成Map
                .collect(Collectors.groupingBy(
                        Map.Entry::getKey,
                        Collectors.mapping(Map.Entry::getValue, Collectors.toList())
                ));
        // 设置nextHandler
        collect.forEach((type, handlers) -> {
            for (int i = 0; i < handlers.size() - 1; i++) {
                handlers.get(i).setNextHandler(handlers.get(i + 1));
            }
        });
        this.handleMap = collect;
    }

    /* *
     * 执行具体业务场景中的责任链集合
     * @param type 对应@Duty注解中的type，可以定义为具体业务场景
     * @param t 被执行的参数*/

    public <T, R> R executeHandle(T t,String... type) {
        Assert.notEmpty(type,"请指定类型");

        List<IHandler> chain =new ArrayList<>();

        for (String anType : type) {
            chain.addAll(handleMap.get(anType));
        }
        chain.sort((h, t1) -> AnnotationUtils.findAnnotation(h.getClass(), Duty.class).order());


        R r = null;
        if (!CollectionUtils.isEmpty(chain)) {
            for (IHandler<T, R> handler : chain) {
                r = handler.handler(t);
            }
        }
        return r;
    }
}
